#include "LCD.h"
#include "Menu.h"
#include "bsp.h"
#include <cc430f6137.h>

uint8_t menuLevel = HOME;
uint8_t menuControl = 0;
uint8_t menuRow = 0;
uint8_t cursorRow = 0;
uint8_t setTemp = 75;
uint8_t ctcTemp = 75;			//Get from CTC
uint8_t numMenuItems[] = {HOME_SIZE, MAIN_MENU_SIZE, INDICATOR_SIZE, 6}; //4th position for # zones
char * menuStrings[] = {"CTC Temperature", "Set Temperature  ",			//Home
												" Zone Information", " Battery Indicator",	//Main Menu
												" Toggle Indicator",												//Indicator
												" A", " B", " C", " D", " E", " F"};				//Zone Info

void main(void)
{
	WDTCTL = WDTPW + WDTHOLD;
	
	LCDinit();
	menuInit();
	while(1)
	{
		if(menuControl)
		{
			menuAction(menuControl);
		}
	}
}

void menuInit(void)
{
	//Make Port2, pins 3-6 inputs with internal pull-ups
	//so that buttons to gnd may be connected
	P2DIR &= ~(BIT3 + BIT4 + BIT5 + BIT6);
	P2REN |= (BIT3 + BIT4 + BIT5 + BIT6);
	P2OUT |= (BIT3 + BIT4 + BIT5 + BIT6);
	
	//enable high->low edge triggered interrupts for the inputs
	P2IES = 0xFF;
	P2IE = (BIT3 + BIT4 + BIT5 + BIT6);
	P2IFG = 0x00;
	__bis_SR_register(GIE);
	
	//display the initial home screen
	printMenu(menuLevel, menuRow);
}

//Handles the flag returned by the menu button interupt
void menuAction(uint8_t control)
{
	char i;		//used for the temporary debounce
	
	switch(control)
	{
		case MENU_UP:
			//If at home, raise the temp.  A limit of 90 degrees is in place
			if(menuLevel == HOME)
			{
				if(setTemp < 90)
				{
					setTemp++;
					printMenu(menuLevel, menuRow);
				}
			}
			//or, if inside the menu...
			else
			{
				//check to see if it is possible to scroll up.  menuRow holds the current position
				//that the cursor is at in a given menu level.
				if(menuRow > 0)
				{
					//if it is, move menuRow up one position
					menuRow--;
					//and decide if the cursor should move, or if the whole menu should scroll
					if(cursorRow > 0)
					{
						moveCursor(MENU_UP);
					}
					//if the cursor doesn't need to move, print the new menu screen
					else
					{
						printMenu(menuLevel, menuRow);
					}
				}
			}
			break;
		case MENU_DOWN:
			//If at home, lower the temp.  A limit of 60 degrees is in place
			if(menuLevel == HOME)
			{
				if(setTemp > 60)
				{
					setTemp--;
					printMenu(menuLevel, menuRow);
				}
			}
			//or, if inside the menu...
			else
			{
				//check to see if it is possible to scroll down.  The -1 is due to menuRow
				//beginning at 0.
				if(menuRow < (numMenuItems[menuLevel] - 1))
				{
					//if it is, move menuRow down one position
					menuRow++;
					//and decide if the cursor should move, or if the whole menu should scroll
					if(cursorRow < 3)
					{
						moveCursor(MENU_DOWN);
					}
					//if the cursor doesn't need to move, print the new menu screen
					else
					{
						printMenu(menuLevel, (menuRow - 3));
					}
				}
			}
			break;
		case MENU_ENTER:
			switch(menuLevel)
			{
				//If menu level is currently home, move to main menu
				case(HOME):
					menuLevel = MAIN_MENU;
					break;
				//If menu level is currently main menu, move to either zone info or
				//indicator, based on cursor position.
				case(MAIN_MENU):
					if(menuRow == 0)
					{
						menuLevel = ZONE_INFO;
					}
					else if(menuRow == 1)
					{
						menuLevel = INDICATOR;
					}
					break;
				case(ZONE_INFO):
					//Figure out how to access different zones.
					break;
				case(INDICATOR):
					batteryIndicator();
					break;
			}
			//Return the menuRow to the top, and print the new menu.
			menuRow = 0;
			moveCursor(HOME);
			printMenu(menuLevel, menuRow);
			break;
		case MENU_BACK:
			switch(menuLevel)
			{
				//If the menu is at a level above main menu, go back to main menu
				case(INDICATOR):
				case(ZONE_INFO):
					menuLevel = MAIN_MENU;
					break;
				//or, if at main menu, return home
				case(MAIN_MENU):
					menuLevel = HOME;
					break;
			}
			//Return the menuRow to the top, and print the new menu.
			menuRow = 0;
			moveCursor(HOME);
			printMenu(menuLevel, menuRow);
			break;
	}
	//Temporary debounce
	for(i=0;i<50;i++)
	{
		delayus(10000);
	}
	P2DIR &= ~(BIT3 + BIT4 + BIT5 + BIT6);		//reenable button inputs
	menuControl = 0;
}

void printMenu(uint8_t level, uint8_t row)
{
	char printMenuStart = 0;
	char i;
	char LCDcursor = 0;
	
	//Begin by clearing the screen, which also returns the cursor to home
	LCDclear();
	
	//Find the correct position in menuStrings[] for the given menuLevel.
	//This is done by adding the values in numMenuItems[]/
	for(i=0; i<level; i++)
	{
		printMenuStart += numMenuItems[i];
	}
	
	//Now, starting at the current menuRow, print up to four items, depending
	//on how many are in the current menuLevel.
	for(i=row; i<numMenuItems[level]; i++)
	{
		LCDmoveCursor(LCDcursor, 0);
		LCDcursor++;
		LCDprintString(menuStrings[printMenuStart + i]);
		
		//This checks to see if the bottom of the LCD has been reached.  If so,
		//stop printing.
		if(LCDcursor > 3)
		{
			break;
		}
	}
	
	//If the home menu has just been printed, also print the temperatures
	if(level == HOME)
	{
		LCDmoveCursor(0, 16);
		LCDprintDecimal(ctcTemp);
		LCDmoveCursor(1, 16);
		LCDprintDecimal(setTemp);
	}
	//otherwise, print the cursor.
	else
	{
		moveCursor(STAY);
	}
}

void moveCursor(uint8_t direction)
{
	//start by clearing the current cursor
	LCDmoveCursor(cursorRow, 0);
	LCDwrite(BLANK);
	
	//Based on the desired direction, change cursor row.  If direction
	//is STAY, then don't change cursorRow.
	switch(direction)
	{
		case MENU_DOWN:
			cursorRow++;
			break;
		case MENU_UP:
			cursorRow--;
			break;
		case HOME:
			cursorRow = 0;
			break;
	}
	
	//Draw the new cursor
	LCDmoveCursor(cursorRow, 0);
	LCDwrite(ARROW);
}

void batteryIndicator(void)
{
}

#pragma vector = PORT2_VECTOR
__interrupt void Port2(void)
{
	//Make Port2, bits 3-6 outputs for debouncing.  Pins should be made inputs
	//again in main, after appropriate button operation has been performed.
	P2DIR |= (BIT3 + BIT4 + BIT5 + BIT6);
	
	//Only one button can be read at a time with this switch statement.  If multiple
	//buttons are pressed, nothing will happen.
	
	P2IFG &= ~(0x87);  //This clears IFG 0,1,2,7.  Not sure why this is needed.
	switch(P2IFG)
	{
		case MENU_UP:				//Bit 3
			menuControl = MENU_UP;
			break;
		case MENU_DOWN:			//Bit 4
			menuControl = MENU_DOWN;
			break;
		case MENU_ENTER:		//Bit 5
			menuControl = MENU_ENTER;
			break;
		case MENU_BACK:			//Bit 6
			menuControl = MENU_BACK;
			break;
		default:
			P2DIR &= ~(BIT3 + BIT4 + BIT5 + BIT6);  //If no valid input, make pins inputs
	}
	// clear the port2 flags
	P2IFG = 0x00;
}
